﻿namespace WPCloudAppIteration2.Phone.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Linq;
    using System.Windows;
    using System.Windows.Threading;
    using Microsoft.Phone.Shell;
    using Microsoft.Samples.WindowsPhoneCloud.StorageClient;

    public class ListBlobsPageViewModel : PivotItemViewModel
    {
        private const string IconsRootUri = "/Toolkit.Content/";

        private readonly ICloudBlobClient blobClient;
        private readonly Dispatcher dispatcher;

        private bool isListing = false;
        private bool hasResults = true;
        private bool useFlatBlobListing = false;
        private string prefix = string.Empty;
        private string message = string.Empty;

        private string containerName;
        private ObservableCollection<string> containerNames = new ObservableCollection<string>();

        public ListBlobsPageViewModel()
            : this(App.CloudClientFactory.ResolveCloudBlobClient("UploadAndList"), Deployment.Current.Dispatcher)
        {
        }

        public ListBlobsPageViewModel(ICloudBlobClient blobClient, Dispatcher dispatcher)
        {
            this.blobClient = blobClient;
            this.dispatcher = dispatcher;
            this.CloudBlobs = new ObservableCollection<ICloudBlob>();
        }

        public event EventHandler<EventArgs> TakePhoto;

        public ObservableCollection<ICloudBlob> CloudBlobs { get; set; }

        public ObservableCollection<string> ContainerNames
        {
            get
            {
                return this.containerNames;
            }

            set
            {
                if (this.containerNames != value)
                {
                    this.containerNames = value;
                    this.NotifyPropertyChanged("ContainerNames");
                }
            }
        }

        public string ContainerName
        {
            get
            {
                return this.containerName;
            }

            set
            {
                if (this.containerName != value)
                {
                    this.containerName = value;
                    this.NotifyPropertyChanged("ContainerName");
                }
            }
        }

        public bool IsListing
        {
            get
            {
                return this.isListing;
            }

            set
            {
                if (this.isListing != value)
                {
                    this.isListing = value;
                    this.NotifyPropertyChanged("IsListing");
                }
            }
        }

        public string Message
        {
            get
            {
                return this.message;
            }

            set
            {
                if (this.message != value)
                {
                    this.message = value;
                    this.NotifyPropertyChanged("Message");
                }
            }
        }

        public bool HasResults
        {
            get
            {
                return this.hasResults;
            }

            set
            {
                if (this.hasResults != value)
                {
                    this.hasResults = value;
                    this.NotifyPropertyChanged("HasResults");
                }
            }
        }

        public string Prefix
        {
            get
            {
                return this.prefix;
            }

            set
            {
                if (this.prefix != value)
                {
                    this.prefix = value;
                    this.NotifyPropertyChanged("Prefix");
                }
            }
        }

        public bool UseFlatBlobListing
        {
            get
            {
                return this.useFlatBlobListing;
            }

            set
            {
                if (this.useFlatBlobListing != value)
                {
                    this.useFlatBlobListing = value;
                    this.NotifyPropertyChanged("UseFlatBlobListing");
                }
            }
        }

        public void ListContainers()
        {
            this.IsListing = true;
            this.Message = "Listing containers...";
            try
            {
                this.blobClient.ListContainers(
                    r =>
                    {
                        if (this.dispatcher != null)
                        {
                            this.dispatcher.BeginInvoke(() => this.UpdateContainerNames(r));
                        }
                        else
                        {
                            this.UpdateContainerNames(r);
                        }
                    });
            }
            catch (Exception exception)
            {
                var errorMessage = StorageClientExceptionParser.ParseDataServiceException(exception).Message;

                this.IsListing = false;
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", errorMessage);
            }
        }

        public void ListBlobs()
        {
            this.IsListing = true;
            this.Message = "Listing blobs...";
            try
            {
                if (!string.IsNullOrWhiteSpace(this.ContainerName))
                {
                    var container = this.blobClient.GetContainerReference(this.ContainerName);
                    container.ListBlobs(
                        this.Prefix,
                        this.UseFlatBlobListing,
                        r =>
                        {
                            if (this.dispatcher != null)
                            {
                                this.dispatcher.BeginInvoke(() => this.UpdateListBlobs(r));
                            }
                            else
                            {
                                this.UpdateListBlobs(r);
                            }
                        });
                }
                else
                {
                    this.IsListing = false;
                    this.Message = "Error: You must select a container.";
                }
            }
            catch (Exception exception)
            {
                var errorMessage = StorageClientExceptionParser.ParseDataServiceException(exception).Message;

                this.IsListing = false;
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", errorMessage);
            }
        }

        public void DeleteBlob(ICloudBlob blob)
        {
            this.Message = "Deleting blob...";
            this.IsListing = true;

            try
            {
                var currentBlob = this.blobClient.GetContainerReference(this.ContainerName).GetBlobReference(blob.Name);
                currentBlob.Delete(
                    true,
                    deletionResult =>
                    {
                        if (this.dispatcher != null)
                        {
                            this.dispatcher.BeginInvoke(() => this.HandleBlobDeletionResult(currentBlob, deletionResult));
                        }
                        else
                        {
                            this.HandleBlobDeletionResult(currentBlob, deletionResult);
                        }
                    });
            }
            catch (Exception exception)
            {
                this.IsListing = false;
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", exception.Message);
            }
        }

        protected override void PopulateApplicationBarButtons(IApplicationBar applicationBar)
        {
            var takePictureButton = new ApplicationBarIconButton(new Uri(string.Format(CultureInfo.InvariantCulture, "{0}{1}", IconsRootUri, "appbar.feature.camera.rest.png"), UriKind.Relative)) { Text = "take picture" };
            takePictureButton.Click += (s, e) => this.RaiseTakePhoto();

            applicationBar.Buttons.Add(takePictureButton);
        }

        private void HandleBlobDeletionResult(ICloudBlob currentBlob, CloudOperationResponse<bool> deletionResult)
        {
            if (deletionResult.Response)
            {
                var listedBlob = this.CloudBlobs.Where(q => q.Name.Equals(currentBlob.Name, StringComparison.InvariantCulture)).SingleOrDefault();
                if (listedBlob != null)
                {
                    this.CloudBlobs.Remove(listedBlob);
                    this.Message = "Changes saved successfully.";
                }
            }
            else
            {
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", deletionResult.Exception.Message);
            }

            this.IsListing = false;
        }

        private void UpdateListBlobs(CloudOperationResponse<IEnumerable<ICloudBlob>> result)
        {
            if (result.Exception == null)
            {
                this.CloudBlobs.Clear();
                foreach (var blob in result.Response)
                {
                    this.CloudBlobs.Add(blob);
                }

                this.HasResults = this.CloudBlobs.Count > 0;
                this.Message = "Listing finished successfully.";
            }
            else
            {
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", result.Exception.Message);
            }

            this.IsListing = false;
        }

        private void UpdateContainerNames(CloudOperationResponse<IEnumerable<ICloudBlobContainer>> result)
        {
            if (result.Exception == null)
            {
                var containerName = this.ContainerName;
                if (this.ContainerNames != null)
                {
                    this.ContainerNames.Clear();
                }

                foreach (var container in result.Response)
                {
                    this.ContainerNames.Add(container.Name);
                }

                if (this.ContainerNames.Contains(containerName))
                {
                    this.ContainerName = containerName;
                }
                else
                {
                    this.ContainerName = this.ContainerNames.FirstOrDefault();
                }

                this.Message = "Listing finished successfully.";
            }
            else
            {
                this.Message = string.Format(CultureInfo.InvariantCulture, "Error: {0}", result.Exception.Message);
            }

            this.IsListing = false;
        }

        private void RaiseTakePhoto()
        {
            var takePhoto = this.TakePhoto;
            if (takePhoto != null)
            {
                takePhoto(this, new EventArgs());
            }
        }
    }
}
